{
    "cells": [
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "# Foooooooooooocus\n",
                "#### Kaggle NoteBook Created by [licyk](https://github.com/licyk)\n",
                "\n",
                "Jupyter Notebook 仓库：[licyk/sd-webui-all-in-one](https://github.com/licyk/sd-webui-all-in-one)\n",
                "\n",
                "这是适用于 [Kaggle](https://www.kaggle.com) 部署 Fooocus 的 Jupyter Notebook，使用时请按顺序执行 Jupyter Notebook 单元。\n",
                "\n",
                "## 功能\n",
                "1. 环境配置：配置安装的 PyTorch 版本、内网穿透的方式。\n",
                "2. 安装 Fooocus：根据环境配置安装 Fooocus 和运行环境。\n",
                "3. 下载模型：下载可选列表中的模型。\n",
                "4. 启动 Fooocus：启动 Fooocus，并显示访问地址。\n",
                "\n",
                "## 提示\n",
                "1. [Ngrok](https://ngrok.com) 内网穿透在使用前需要填写 Ngrok Token，可在 [Ngrok](https://ngrok.com) 官网获取。\n",
                "2. 已知 CloudFlare、Gradio 内网穿透会导致 [Kaggle](https://www.kaggle.com) 平台强制关机，在使用 [Kaggle](https://www.kaggle.com) 平台时请勿勾选这两个选项。\n",
                "3. 请不要生成违禁图片，这将导致 Kaggle 账号被永久封禁！"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "### 参数配置\n",
                "1. [[下一个单元 →](#安装-Fooocus)]"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "# 消息格式输出\n",
                "def echo(*args):\n",
                "    for i in args:\n",
                "        print(f\":: {i}\")\n",
                "\n",
                "\n",
                "\n",
                "# ARIA2\n",
                "class ARIA2:\n",
                "    WORKSPACE = \"\"\n",
                "    WORKFOLDER = \"\"\n",
                "\n",
                "\n",
                "    def __init__(self, workspace, workfolder) -> None:\n",
                "        self.WORKSPACE = workspace\n",
                "        self.WORKFOLDER = workfolder\n",
                "\n",
                "\n",
                "    # 下载器\n",
                "    def aria2(self, url, path, filename):\n",
                "        import os\n",
                "        if not os.path.exists(path + \"/\" + filename):\n",
                "            echo(f\"开始下载 {filename} ，路径: {path}/{filename}\")\n",
                "            !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M \"{url}\" -d \"{path}\" -o \"{filename}\"\n",
                "            if os.path.exists(path + \"/\" + filename) and not os.path.exists(path + \"/\" + filename + \".aria2\"):\n",
                "                echo(f\"{filename} 下载完成\")\n",
                "            else:\n",
                "                echo(f\"{filename} 下载中断\")\n",
                "        else:\n",
                "            if os.path.exists(path + \"/\" + filename + \".aria2\"):\n",
                "                echo(f\"开始下载 {filename} ，路径: {path}/{filename}\")\n",
                "                !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M \"{url}\" -d \"{path}\" -o \"{filename}\"\n",
                "                if os.path.exists(path + \"/\" + filename) and not os.path.exists(path + \"/\" + filename + \".aria2\"):\n",
                "                    echo(f\"{filename} 下载完成\")\n",
                "                else:\n",
                "                    echo(f\"{filename} 下载中断\")\n",
                "            else:\n",
                "                echo(f\"{filename} 文件已存在，路径: {path}/{filename}\")\n",
                "\n",
                "\n",
                "    # 大模型下载\n",
                "    def get_sd_model(self, url, filename):\n",
                "        pass\n",
                "\n",
                "\n",
                "    # lora下载\n",
                "    def get_lora_model(self, url, filename):\n",
                "        pass\n",
                "\n",
                "\n",
                "\n",
                "# GIT\n",
                "class GIT:\n",
                "    WORKSPACE = \"\"\n",
                "    WORKFOLDER = \"\"\n",
                "\n",
                "\n",
                "    def __init__(self, workspace, workfolder) -> None:\n",
                "        self.WORKSPACE = workspace\n",
                "        self.WORKFOLDER = workfolder\n",
                "\n",
                "\n",
                "    # 检测要克隆的项目是否存在于指定路径\n",
                "    def exists(self, addr=None, path=None, name=None):\n",
                "        import os\n",
                "        if addr is not None:\n",
                "            if path is None and name is None:\n",
                "                path = os.getcwd() + \"/\" + addr.split(\"/\").pop().split(\".git\", 1)[0]\n",
                "            elif path is None and name is not None:\n",
                "                path = os.getcwd() + \"/\" + name\n",
                "            elif path is not None and name is None:\n",
                "                path = os.path.normpath(path) + \"/\" + addr.split(\"/\").pop().split(\".git\", 1)[0]\n",
                "\n",
                "        if os.path.exists(path):\n",
                "            return True\n",
                "        else:\n",
                "            return False\n",
                "\n",
                "\n",
                "    # 克隆项目\n",
                "    def clone(self, addr, path=None, name=None):\n",
                "        import os\n",
                "        repo = addr.split(\"/\").pop().split(\".git\", 1)[0]\n",
                "        if not self.exists(addr, path, name):\n",
                "            echo(f\"开始下载 {repo}\")\n",
                "            if path is None and name is None:\n",
                "                path = os.getcwd()\n",
                "                name = repo\n",
                "            elif path is not None and name is None:\n",
                "                name = repo\n",
                "            elif path is None and name is not None:\n",
                "                path = os.getcwd()\n",
                "            !git clone {addr} \"{path}/{name}\" --recurse-submodules\n",
                "        else:\n",
                "            echo(f\"{repo} 已存在\")\n",
                "\n",
                "\n",
                "\n",
                "# TUNNEL\n",
                "class TUNNEL:\n",
                "    LOCALHOST_RUN = \"localhost.run\"\n",
                "    REMOTE_MOE = \"remote.moe\"\n",
                "    WORKSPACE = \"\"\n",
                "    WORKFOLDER = \"\"\n",
                "    PORT = \"\"\n",
                "\n",
                "\n",
                "    def __init__(self, workspace, workfolder, port) -> None:\n",
                "        self.WORKSPACE = workspace\n",
                "        self.WORKFOLDER = workfolder\n",
                "        self.PORT = port\n",
                "\n",
                "\n",
                "    # ngrok内网穿透\n",
                "    def ngrok(self, ngrok_token: str):\n",
                "        from pyngrok import conf, ngrok\n",
                "        conf.get_default().auth_token = ngrok_token\n",
                "        conf.get_default().monitor_thread = False\n",
                "        port = self.PORT\n",
                "        ssh_tunnels = ngrok.get_tunnels(conf.get_default())\n",
                "        if len(ssh_tunnels) == 0:\n",
                "            ssh_tunnel = ngrok.connect(port, bind_tls=True)\n",
                "            return ssh_tunnel.public_url\n",
                "        else:\n",
                "            return ssh_tunnels[0].public_url\n",
                "\n",
                "\n",
                "    # cloudflare内网穿透\n",
                "    def cloudflare(self):\n",
                "        from pycloudflared import try_cloudflare\n",
                "        port = self.PORT\n",
                "        urls = try_cloudflare(port).tunnel\n",
                "        return urls\n",
                "\n",
                "\n",
                "    from typing import Union\n",
                "    from pathlib import Path\n",
                "\n",
                "    # 生成ssh密钥\n",
                "    def gen_key(self, path: Union[str, Path]) -> None:\n",
                "        import subprocess\n",
                "        import shlex\n",
                "        from pathlib import Path\n",
                "        path = Path(path)\n",
                "        arg_string = f'ssh-keygen -t rsa -b 4096 -N \"\" -q -f {path.as_posix()}'\n",
                "        args = shlex.split(arg_string)\n",
                "        subprocess.run(args, check=True)\n",
                "        path.chmod(0o600)\n",
                "\n",
                "\n",
                "    # ssh内网穿透\n",
                "    def ssh_tunnel(self, host: str) -> None:\n",
                "        import subprocess\n",
                "        import atexit\n",
                "        import shlex\n",
                "        import re\n",
                "        import os\n",
                "        from pathlib import Path\n",
                "        from tempfile import TemporaryDirectory\n",
                "\n",
                "        ssh_name = \"id_rsa\"\n",
                "        ssh_path = Path(self.WORKSPACE) / ssh_name\n",
                "        port = self.PORT\n",
                "\n",
                "        tmp = None\n",
                "        if not ssh_path.exists():\n",
                "            try:\n",
                "                self.gen_key(ssh_path)\n",
                "            # write permission error or etc\n",
                "            except subprocess.CalledProcessError:\n",
                "                tmp = TemporaryDirectory()\n",
                "                ssh_path = Path(tmp.name) / ssh_name\n",
                "                self.gen_key(ssh_path)\n",
                "\n",
                "        arg_string = f\"ssh -R 80:127.0.0.1:{port} -o StrictHostKeyChecking=no -i {ssh_path.as_posix()} {host}\"\n",
                "        args = shlex.split(arg_string)\n",
                "\n",
                "        tunnel = subprocess.Popen(\n",
                "            args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding=\"utf-8\"\n",
                "        )\n",
                "\n",
                "        atexit.register(tunnel.terminate)\n",
                "        if tmp is not None:\n",
                "            atexit.register(tmp.cleanup)\n",
                "\n",
                "        tunnel_url = \"\"\n",
                "        LOCALHOST_RUN = self.LOCALHOST_RUN\n",
                "        lines = 27 if host == LOCALHOST_RUN else 5\n",
                "        localhostrun_pattern = re.compile(r\"(?P<url>https?://\\S+\\.lhr\\.life)\")\n",
                "        remotemoe_pattern = re.compile(r\"(?P<url>https?://\\S+\\.remote\\.moe)\")\n",
                "        pattern = localhostrun_pattern if host == LOCALHOST_RUN else remotemoe_pattern\n",
                "\n",
                "        for _ in range(lines):\n",
                "            line = tunnel.stdout.readline()\n",
                "            if line.startswith(\"Warning\"):\n",
                "                print(line, end=\"\")\n",
                "\n",
                "            url_match = pattern.search(line)\n",
                "            if url_match:\n",
                "                tunnel_url = url_match.group(\"url\")\n",
                "                if lines == 27:\n",
                "                    os.environ['LOCALHOST_RUN'] = tunnel_url\n",
                "                    return tunnel_url\n",
                "                else:\n",
                "                    os.environ['REMOTE_MOE'] = tunnel_url\n",
                "                    return tunnel_url\n",
                "                # break\n",
                "        else:\n",
                "            echo(f\"启动 {host} 内网穿透失败\")\n",
                "\n",
                "\n",
                "    # localhost.run穿透\n",
                "    def localhost_run(self):\n",
                "        urls = self.ssh_tunnel(self.LOCALHOST_RUN)\n",
                "        return urls\n",
                "\n",
                "\n",
                "    # remote.moe内网穿透\n",
                "    def remote_moe(self):\n",
                "        urls = self.ssh_tunnel(self.REMOTE_MOE)\n",
                "        return urls\n",
                "\n",
                "\n",
                "    # gradio内网穿透\n",
                "    def gradio(self):\n",
                "        import subprocess\n",
                "        import shlex\n",
                "        import atexit\n",
                "        import re\n",
                "        port = self.PORT\n",
                "        cmd = f\"gradio-tunneling --port {port}\"\n",
                "        cmd = shlex.split(cmd)\n",
                "        tunnel = subprocess.Popen(\n",
                "            cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding=\"utf-8\"\n",
                "        )\n",
                "\n",
                "        atexit.register(tunnel.terminate)\n",
                "\n",
                "        tunnel_url = \"\"\n",
                "        lines = 5\n",
                "        gradio_pattern = re.compile(r\"(?P<url>https?://\\S+\\.gradio\\.live)\")\n",
                "        pattern = gradio_pattern\n",
                "\n",
                "        for _ in range(lines):\n",
                "            line = tunnel.stdout.readline()\n",
                "            if line.startswith(\"Warning\"):\n",
                "                print(line, end=\"\")\n",
                "            url_match = pattern.search(line)\n",
                "            if url_match:\n",
                "                tunnel_url = url_match.group(\"url\")\n",
                "                return tunnel_url\n",
                "        else:\n",
                "            echo(f\"启动 Gradio 内网穿透失败\")\n",
                "\n",
                "\n",
                "    # 启动内网穿透\n",
                "    def start(self, ngrok=False, ngrok_token=None, cloudflare=False, remote_moe=False, localhost_run=False, gradio=False):\n",
                "        if cloudflare is True or ngrok is True or ngrok_token is not None or remote_moe is True or localhost_run is True or gradio is True:\n",
                "            echo(\"启动内网穿透\")\n",
                "\n",
                "        if cloudflare is True:\n",
                "            cloudflare_url = self.cloudflare()\n",
                "        else:\n",
                "            cloudflare_url = None\n",
                "\n",
                "        if ngrok is True and ngrok_token is not None:\n",
                "            ngrok_url = self.ngrok(ngrok_token)\n",
                "        else:\n",
                "            ngrok_url = None\n",
                "\n",
                "        if remote_moe is True:\n",
                "            remote_moe_url = self.remote_moe()\n",
                "        else:\n",
                "            remote_moe_url = None\n",
                "\n",
                "        if localhost_run is True:\n",
                "            localhost_run_url = self.localhost_run()\n",
                "        else:\n",
                "            localhost_run_url = None\n",
                "\n",
                "        if gradio is True:\n",
                "            gradio_url = self.gradio()\n",
                "        else:\n",
                "            gradio_url = None\n",
                "\n",
                "        echo(\"下方为访问地址\")\n",
                "        print(\"==================================================================================\")\n",
                "        echo(f\"CloudFlare: {cloudflare_url}\")\n",
                "        echo(f\"Ngrok: {ngrok_url}\")\n",
                "        echo(f\"remote.moe: {remote_moe_url}\")\n",
                "        echo(f\"localhost_run: {localhost_run_url}\")\n",
                "        echo(f\"Gradio: {gradio_url}\")\n",
                "        print(\"==================================================================================\")\n",
                "\n",
                "\n",
                "\n",
                "\n",
                "# ENV\n",
                "class ENV:\n",
                "    WORKSPACE = \"\"\n",
                "    WORKFOLDER = \"\"\n",
                "\n",
                "\n",
                "    def __init__(self, workspace, workfolder) -> None:\n",
                "        self.WORKSPACE = workspace\n",
                "        self.WORKFOLDER = workfolder\n",
                "\n",
                "\n",
                "    # 准备ipynb笔记自身功能的依赖\n",
                "    def prepare_env_depend(self, use_mirror=True):\n",
                "        if use_mirror is True:\n",
                "            pip_mirror = \"--index-url https://mirrors.cloud.tencent.com/pypi/simple --find-links https://mirror.sjtu.edu.cn/pytorch-wheels/cu121/torch_stable.html\"\n",
                "        else:\n",
                "            pip_mirror = \"--index-url https://pypi.python.org/simple --find-links https://download.pytorch.org/whl/cu121/torch_stable.html\"\n",
                "\n",
                "        echo(\"安装自身组件依赖\")\n",
                "        !pip install pyngrok pycloudflared gradio-tunneling {pip_mirror}\n",
                "        !apt update\n",
                "        !apt install aria2 ssh google-perftools -y\n",
                "\n",
                "\n",
                "    # 安装pytorch和xformers\n",
                "    def prepare_torch(self, torch_ver, xformers_ver, use_mirror=False):\n",
                "        arg = \"--no-deps\"\n",
                "        if use_mirror is True:\n",
                "            pip_mirror = \"--index-url https://mirrors.cloud.tencent.com/pypi/simple --find-links https://mirror.sjtu.edu.cn/pytorch-wheels/cu121/torch_stable.html\"\n",
                "        else:\n",
                "            pip_mirror = \"--index-url https://pypi.python.org/simple --find-links https://download.pytorch.org/whl/cu121/torch_stable.html\"\n",
                "\n",
                "        if torch_ver != \"\":\n",
                "            echo(\"安装 PyTorch\")\n",
                "            !pip install {torch_ver} {pip_mirror}\n",
                "        if xformers_ver != \"\":\n",
                "            echo(\"安装 xFormers\")\n",
                "            !pip install {xformers_ver} {pip_mirror} {arg}\n",
                "\n",
                "\n",
                "    # python软件包安装\n",
                "    # 可使用的操作:\n",
                "    # 安装: install -> install\n",
                "    # 仅安装: install_single -> install --no-deps\n",
                "    # 强制重装: force_install -> install --force-reinstall\n",
                "    # 仅强制重装: force_install_single -> install --force-reinstall --no-deps\n",
                "    # 更新: update -> install --upgrade\n",
                "    # 卸载: uninstall -y\n",
                "    def py_pkg_manager(self, pkg, type=None, use_mirror=False):\n",
                "        if use_mirror is True:\n",
                "            pip_mirror = \"--index-url https://mirrors.cloud.tencent.com/pypi/simple --find-links https://mirror.sjtu.edu.cn/pytorch-wheels/cu121/torch_stable.html\"\n",
                "        else:\n",
                "            pip_mirror = \"--index-url https://pypi.python.org/simple --find-links https://download.pytorch.org/whl/cu121/torch_stable.html\"\n",
                "\n",
                "        if type == \"install\":\n",
                "            func = \"install\"\n",
                "            args = \"\"\n",
                "        elif type == \"install_single\":\n",
                "            func = \"install\"\n",
                "            args = \"--no-deps\"\n",
                "        elif type == \"force_install\":\n",
                "            func = \"install\"\n",
                "            args = \"--force-reinstall\"\n",
                "        elif type == \"force_install_single\":\n",
                "            func = \"install\"\n",
                "            args = \"install --force-reinstall --no-deps\"\n",
                "        elif type == \"update\":\n",
                "            func = \"install\"\n",
                "            args = \"--upgrade\"\n",
                "        elif type == \"uninstall\":\n",
                "            func = \"uninstall\"\n",
                "            args = \"-y\"\n",
                "            pip_mirror = \"\"\n",
                "        else:\n",
                "            echo(f\"未知操作: {type}\")\n",
                "            return\n",
                "        echo(f\"执行操作: pip {func} {pkg} {args} {pip_mirror}\")\n",
                "        !pip {func} {pkg} {args} {pip_mirror}\n",
                "\n",
                "\n",
                "    # 安装requirements.txt依赖\n",
                "    def install_requirements(self, path, use_mirror=False):\n",
                "        import os\n",
                "        if use_mirror is True:\n",
                "            pip_mirror = \"--index-url https://mirrors.cloud.tencent.com/pypi/simple --find-links https://mirror.sjtu.edu.cn/pytorch-wheels/cu121/torch_stable.html\"\n",
                "        else:\n",
                "            pip_mirror = \"--index-url https://pypi.python.org/simple --find-links https://download.pytorch.org/whl/cu121/torch_stable.html\"\n",
                "        if os.path.exists(path):\n",
                "            echo(\"安装依赖\")\n",
                "            !pip install -r \"{path}\" {pip_mirror}\n",
                "        else:\n",
                "            echo(\"依赖文件路径为空\")\n",
                "\n",
                "\n",
                "    # 配置内存优化\n",
                "    def tcmalloc(self):\n",
                "        echo(\"配置内存优化\")\n",
                "        import os\n",
                "        os.environ[\"LD_PRELOAD\"] = \"/usr/lib/x86_64-linux-gnu/libtcmalloc_minimal.so.4\"\n",
                "\n",
                "\n",
                "\n",
                "# MANAGER\n",
                "class MANAGER:\n",
                "    WORKSPACE = \"\"\n",
                "    WORKFOLDER = \"\"\n",
                "\n",
                "\n",
                "    def __init__(self, workspace, workfolder) -> None:\n",
                "        self.WORKSPACE = workspace\n",
                "        self.WORKFOLDER = workfolder\n",
                "\n",
                "\n",
                "    # 清理ipynb笔记的输出\n",
                "    def clear_up(self, opt):\n",
                "        from IPython.display import clear_output\n",
                "        clear_output(wait=opt)\n",
                "\n",
                "\n",
                "    # 检查gpu是否可用\n",
                "    def check_gpu(self):\n",
                "        echo(\"检测 GPU 是否可用\")\n",
                "        import tensorflow as tf\n",
                "        echo(f\"TensorFlow 版本: {tf.__version__}\")\n",
                "        if tf.test.gpu_device_name():\n",
                "            echo(\"GPU 可用\")\n",
                "        else:\n",
                "            echo(\"GPU 不可用\")\n",
                "            raise Exception(\"\\n没有使用GPU，请在代码执行程序-更改运行时类型-设置为GPU！\\n如果不能使用GPU，建议更换账号！\")\n",
                "\n",
                "\n",
                "    # 配置google drive\n",
                "    def config_google_drive(self):\n",
                "        echo(\"挂载 Google Drive\")\n",
                "        import os\n",
                "        if not os.path.exists('/content/drive/MyDrive'):\n",
                "            from google.colab import drive\n",
                "            drive.mount('/content/drive')\n",
                "            echo(\"Google Dirve 挂载完成\")\n",
                "        else:\n",
                "            echo(\"Google Drive 已挂载\")\n",
                "\n",
                "        # 检测并创建输出文件夹\n",
                "        if os.path.exists('/content/drive/MyDrive'):\n",
                "            if not os.path.exists('/content/drive/MyDrive/fooocus_output'):\n",
                "                echo(\"在 Google Drive 创建 fooocus_ouput 文件夹\")\n",
                "                !mkdir -p /content/drive/MyDrive/fooocus_output\n",
                "        else:\n",
                "            raise Exception(\"未挂载 Google Drive，请重新挂载后重试！\")\n",
                "\n",
                "\n",
                "\n",
                "# FOOOCUS\n",
                "class FOOOCUS(ARIA2, GIT, TUNNEL, MANAGER, ENV):\n",
                "    WORKSPACE = \"\"\n",
                "    WORKFOLDER = \"\"\n",
                "\n",
                "    tun = TUNNEL(WORKSPACE, WORKFOLDER, 7865)\n",
                "\n",
                "    def __init__(self, workspace, workfolder) -> None:\n",
                "        self.WORKSPACE = workspace\n",
                "        self.WORKFOLDER = workfolder\n",
                "\n",
                "\n",
                "    # 下载大模型\n",
                "    def get_sd_model(self, url, filename = None):\n",
                "        path = self.WORKSPACE + \"/\" + self.WORKFOLDER + \"/models/checkpoints\"\n",
                "        filename = url.split(\"/\").pop() if filename is None else filename\n",
                "        super().aria2(url, path, filename)\n",
                "\n",
                "\n",
                "    # 下载lora模型\n",
                "    def get_lora_model(self, url, filename = None):\n",
                "        path = self.WORKSPACE + \"/\" + self.WORKFOLDER + \"/models/loras\"\n",
                "        filename = url.split(\"/\").pop() if filename is None else filename\n",
                "        super().aria2(url, path, filename)\n",
                "\n",
                "\n",
                "    # 下载配置文件\n",
                "    def install_config(self):\n",
                "        path = self.WORKSPACE + \"/\" + self.WORKFOLDER\n",
                "        echo(\"下载配置文件\")\n",
                "        self.aria2(\"https://github.com/licyk/sd-webui-all-in-one/releases/download/archive/fooocus_config.json\", path + \"/presets\", \"custom.json\")\n",
                "        self.aria2(\"https://github.com/licyk/sd-webui-all-in-one/releases/download/archive/fooocus_path_config_kaggle.json\", path, \"config.txt\")\n",
                "        self.aria2(\"https://github.com/licyk/sd-webui-all-in-one/releases/download/archive/fooocus_zh_cn.json\", path + \"/language\", \"zh.json\")\n",
                "\n",
                "\n",
                "    # 安装fooocus\n",
                "    def install(self, torch_ver, xformers_ver, use_mirror):\n",
                "        import os\n",
                "        os.chdir(self.WORKSPACE)\n",
                "        self.check_gpu()\n",
                "        self.prepare_env_depend(use_mirror)\n",
                "        self.clone(\"https://github.com/lllyasviel/Fooocus\", self.WORKSPACE)\n",
                "        os.chdir(f\"{self.WORKSPACE}/{self.WORKFOLDER}\")\n",
                "        self.prepare_torch(torch_ver, xformers_ver, use_mirror)\n",
                "        req_file = self.WORKSPACE + \"/\" + self.WORKFOLDER + \"/requirements_versions.txt\"\n",
                "        self.install_requirements(req_file, use_mirror)\n",
                "        self.py_pkg_manager(\"numpy==1.26.4\", \"force_install\", use_mirror)\n",
                "        self.install_config()\n",
                "        self.tcmalloc()\n",
                "\n",
                "\n",
                "#######################################################\n",
                "try:    \n",
                "    echo(\"尝试安装 ipywidgets 组件\")\n",
                "    !pip install ipywidgets -qq\n",
                "    from IPython.display import clear_output\n",
                "    clear_output(wait=False)\n",
                "    INIT_CONFIG = 1\n",
                "except:\n",
                "    raise Exception(\"未初始化功能\")\n",
                "\n",
                "import ipywidgets as widgets\n",
                "\n",
                "\n",
                "# PyTorch 版本\n",
                "pytorch_ver = widgets.Textarea(value=\"torch==2.2.1+cu121 torchvision==0.17.1+cu121 torchaudio==2.2.1+cu121\", placeholder=\"请填写 PyTorch 版本\", description=\"PyTorch 版本: \", disabled=False)\n",
                "xformers_ver = widgets.Textarea(value=\"xformers==0.0.25\", placeholder=\"请填写 xFormers 版本\", description=\"xFormers 版本: \", disabled=False)\n",
                "# 内网穿透方式\n",
                "use_remote_moe = widgets.Checkbox(value=True, description=\"使用 remote.moe 内网穿透\", disabled=False)\n",
                "use_localhost_run = widgets.Checkbox(value=True, description=\"使用 localhost.run 内网穿透\", disabled=False) #@param {type:\"boolean\"}\n",
                "use_cloudflare = widgets.Checkbox(value=False, description=\"使用 CloudFlare 内网穿透\", disabled=False) #@param {type:\"boolean\"}\n",
                "use_ngrok = widgets.Checkbox(value=False, description=\"使用 Ngrok 内网穿透\", disabled=False) #@param {type:\"boolean\"}\n",
                "ngrok_token = widgets.Textarea(value=\"\", placeholder=\"请填写 Ngrok Token（可在 Ngrok 官网获取）\", description=\"Ngrok Token: \", disabled=False)  #@param {type:\"string\"}\n",
                "use_gradio = widgets.Checkbox(value=False, description=\"使用 Gradio 内网穿透\", disabled=False) #@param {type:\"boolean\"}\n",
                "# 模型下载\n",
                "sd_xl_base = widgets.Checkbox(value=False, description=\"下载 sd_xl_base 模型\", disabled=False)\n",
                "kohakuXLGamma_rev1 = widgets.Checkbox(value=False, description=\"下载 kohakuXLGamma_rev1 模型\", disabled=False)\n",
                "kohakuXLBeta_beta7 = widgets.Checkbox(value=False, description=\"下载 kohakuXLBeta_beta7 模型\", disabled=False)\n",
                "Kohaku_XL_Delta = widgets.Checkbox(value=False, description=\"下载 Kohaku_XL_Delta 模型\", disabled=False)\n",
                "kohakuXL_Epsilon = widgets.Checkbox(value=True, description=\"下载 kohakuXL_Epsilon 模型\", disabled=False)\n",
                "animagine_XL_3 = widgets.Checkbox(value=False, description=\"下载 animagine_XL_3 模型\", disabled=False)\n",
                "animagine_XL_3_1 = widgets.Checkbox(value=True, description=\"下载 animagine_XL_3_1 模型\", disabled=False)\n",
                "heart_of_apple_xl = widgets.Checkbox(value=False, description=\"下载 heart_of_apple_xl 模型\", disabled=False)\n",
                "CounterfeitXL = widgets.Checkbox(value=False, description=\"下载 CounterfeitXL 模型\", disabled=False)\n",
                "bluePencilXL  = widgets.Checkbox(value=False, description=\"下载 bluePencilXL 模型\", disabled=False)\n",
                "animeIllustDiffusion = widgets.Checkbox(value=False, description=\"下载 animeIllustDiffusion 模型\", disabled=False)\n",
                "nekorayxl = widgets.Checkbox(value=False, description=\"下载 nekorayxl 模型\", disabled=False)\n",
                "anima_pencil_xl = widgets.Checkbox(value=False, description=\"下载 anima_pencil_xl 模型\", disabled=False)\n",
                "BArtstyleDB = widgets.Checkbox(value=False, description=\"下载 BArtstyleDB 模型\", disabled=False)\n",
                "pony_v6 = widgets.Checkbox(value=False, description=\"下载 pony_v6 模型\", disabled=False)\n",
                "# 自定义模型下载\n",
                "model_url = widgets.Textarea(value=\"\", placeholder=\"请填写模型下载链接\", description=\"模型链接: \", disabled=False)  #@param {type:\"string\"}\n",
                "model_name = widgets.Textarea(value=\"\", placeholder=\"请填写模型名称，包括后缀名，例：kohaku-xl.safetensors\", description=\"模型名称: \", disabled=False)  #@param {type:\"string\"}\n",
                "model_type = widgets.Dropdown(options=[(\"Stable Diffusion 模型（大模型）\", \"sd\"), (\"LoRA 模型\", \"lora\")], value=\"sd\", description='模型种类: ')\n",
                "# 创建实例\n",
                "fooocus = FOOOCUS(\"/kaggle\",\"Fooocus\")\n",
                "display(pytorch_ver, # PyTorch\n",
                "        xformers_ver,\n",
                "        use_remote_moe, # 内网穿透\n",
                "        use_localhost_run,\n",
                "        use_cloudflare,\n",
                "        use_gradio,\n",
                "        use_ngrok,\n",
                "        ngrok_token,\n",
                "        sd_xl_base, # 模型下载\n",
                "        kohakuXLGamma_rev1,\n",
                "        kohakuXLBeta_beta7,\n",
                "        Kohaku_XL_Delta,\n",
                "        kohakuXL_Epsilon,\n",
                "        animagine_XL_3,\n",
                "        animagine_XL_3_1,\n",
                "        heart_of_apple_xl,\n",
                "        CounterfeitXL,\n",
                "        bluePencilXL,\n",
                "        animeIllustDiffusion,\n",
                "        nekorayxl,\n",
                "        heart_of_apple_xl,\n",
                "        anima_pencil_xl,\n",
                "        BArtstyleDB,\n",
                "        pony_v6,\n",
                "        model_url, # 自定义模型下载\n",
                "        model_name,\n",
                "        model_type\n",
                "        )\n",
                "\n",
                "echo(\"配置参数完成\")"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "### 安装 Fooocus\n",
                "2. [[← 上一个单元](#参数配置)|[下一个单元 →](#启动-Fooocus)]"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {},
            "outputs": [],
            "source": [
                "try:    \n",
                "    i = INIT_CONFIG\n",
                "    INIT_CONFIG_1 = 1\n",
                "except:\n",
                "    raise Exception(\"未运行\\\"参数配置\\\"单元\")\n",
                "\n",
                "fooocus.install(pytorch_ver.value, xformers_ver.value, False)\n",
                "fooocus.clear_up(False)\n",
                "echo(\"Fooocus 运行环境配置完成\")\n",
                "\n",
                "# 预设模型下载\n",
                "echo(\"下载模型中\")\n",
                "if sd_xl_base.value:\n",
                "    fooocus.get_sd_model(\"https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/resolve/main/sd_xl_base_1.0_0.9vae.safetensors\", \"sd_xl_base_1.0_0.9vae.safetensors\")\n",
                "if kohakuXLGamma_rev1.value:\n",
                "    fooocus.get_sd_model(\"https://huggingface.co/KBlueLeaf/Kohaku-XL-gamma/resolve/main/kohaku-xl-gamma-rev1.safetensors\", \"kohakuXLGamma_rev1.safetensors\")\n",
                "if kohakuXLBeta_beta7.value:\n",
                "    fooocus.get_sd_model(\"https://huggingface.co/licyk/sd-model/resolve/main/sdxl_1.0/kohakuXLBeta_beta7.safetensors\", \"kohakuXLBeta_beta7.safetensors\")\n",
                "if Kohaku_XL_Delta.value:\n",
                "    fooocus.get_sd_model(\"https://huggingface.co/KBlueLeaf/Kohaku-XL-Delta/resolve/main/kohaku-xl-delta-rev1.safetensors\", \"kohaku-xl-delta-rev1.safetensors\")\n",
                "if kohakuXL_Epsilon.value:\n",
                "    fooocus.get_sd_model(\"https://huggingface.co/KBlueLeaf/Kohaku-XL-Epsilon/resolve/main/kohaku-xl-epsilon-rev1.safetensors\", \"kohaku-xl-epsilon-rev1.safetensors\")\n",
                "if animagine_XL_3_1.value:\n",
                "    fooocus.get_sd_model(\"https://huggingface.co/cagliostrolab/animagine-xl-3.1/resolve/main/animagine-xl-3.1.safetensors\", \"animagine-xl-3.1.safetensors\")\n",
                "if animagine_XL_3.value:\n",
                "    fooocus.get_sd_model(\"https://huggingface.co/cagliostrolab/animagine-xl-3.0/resolve/main/animagine-xl-3.0.safetensors\", \"animagine-xl-3.0.safetensors\")\n",
                "if CounterfeitXL.value:\n",
                "    fooocus.get_sd_model(\"https://huggingface.co/licyk/sd-model/resolve/main/sdxl_1.0/CounterfeitXL-V1.0.safetensors\", \"CounterfeitXL-V1.0.safetensors\")\n",
                "if bluePencilXL.value:\n",
                "    fooocus.get_sd_model(\"https://civitai.com/api/download/models/323375\", \"bluePencilXL_v050.safetensors\")\n",
                "if animeIllustDiffusion.value:\n",
                "    fooocus.get_sd_model(\"https://huggingface.co/licyk/sd-model/resolve/main/sdxl_1.0/animeIllustDiffusion_v061.safetensors\", \"animeIllustDiffusion_v061.safetensors\")\n",
                "if nekorayxl.value:\n",
                "    fooocus.get_sd_model(\"https://huggingface.co/licyk/sd-model/resolve/main/sdxl_1.0/nekorayxl_v06W3.safetensors\", \"nekorayxl_v06W3.safetensors\")\n",
                "if heart_of_apple_xl.value:\n",
                "    fooocus.get_sd_model(\"https://civitai.com/api/download/models/337306\", \"heart-of-apple-xl.safetensors\")\n",
                "if anima_pencil_xl.value:\n",
                "    fooocus.get_sd_model(\"https://civitai.com/api/download/models/323674\", \"anima_pencil_xl.safetensors\")\n",
                "if BArtstyleDB.value:\n",
                "    fooocus.get_sd_model(\"https://civitai.com/api/download/models/299095\", \"BArtstyleDB_XL.safetensors\")\n",
                "if pony_v6.value:\n",
                "    fooocus.get_sd_model(\"https://civitai.com/api/download/models/290640\", \"ponyDiffusionV6XL_v6StartWithThisOne.safetensors\")\n",
                "\n",
                "# 自定义模型下载\n",
                "echo(\"下载自定义模型中\")\n",
                "if model_url.value != \"\" and model_name.value != \"\":\n",
                "    if model_type.value == \"sd\":\n",
                "        fooocus.get_sd_model(model_url.value, model_name.value)\n",
                "    elif model_type.value == \"lora\":\n",
                "        fooocus.get_lora_model(model_url.value, model_name.value)\n",
                "else:\n",
                "    echo(\"自定义模型下载未填写模型链接或者模型名称，请检查\")\n",
                "echo(\"模型下载完成\")"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "### 启动 Fooocus\n",
                "3. [[← 上一个单元](#安装-Fooocus)]"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": null,
            "metadata": {
                "trusted": true
            },
            "outputs": [],
            "source": [
                "try:    \n",
                "    i = INIT_CONFIG_1\n",
                "except:\n",
                "    raise Exception(\"未运行\\\"安装\\\"单元\")\n",
                "\n",
                "echo(\"启动 Fooocus\")\n",
                "fooocus.tun.start(ngrok=use_ngrok.value, ngrok_token=ngrok_token.value, cloudflare=use_cloudflare.value, remote_moe=use_remote_moe.value, localhost_run=use_localhost_run.value, gradio=use_gradio.value)\n",
                "!python /kaggle/Fooocus/launch.py --preset custom --language zh --disable-offload-from-vram --async-cuda-allocation\n",
                "fooocus.clear_up(False)\n",
                "echo(\"已关闭 Fooocus\")"
            ]
        }
    ],
    "metadata": {
        "kaggle": {
            "accelerator": "nvidiaTeslaT4",
            "dataSources": [],
            "dockerImageVersionId": 30646,
            "isGpuEnabled": true,
            "isInternetEnabled": true,
            "language": "python",
            "sourceType": "notebook"
        },
        "kernelspec": {
            "display_name": "Python 3",
            "language": "python",
            "name": "python3"
        },
        "language_info": {
            "codemirror_mode": {
                "name": "ipython",
                "version": 3
            },
            "file_extension": ".py",
            "mimetype": "text/x-python",
            "name": "python",
            "nbconvert_exporter": "python",
            "pygments_lexer": "ipython3",
            "version": "3.10.11"
        }
    },
    "nbformat": 4,
    "nbformat_minor": 4
}
